package com.lagou.edu.datasource;

import com.lagou.edu.zk.ZkHelper;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.sql.DataSource;

/**
 * 数据源工厂
 */
@Slf4j
@Component("zkDatasource")
public class ZkDataSourceFactory extends AbstractFactoryBean<DataSource> {
    private static HikariDataSource dataSource = null;
    private static String addr;
    private static String username;
    private static String password;

    static {
        // 启动时初始化默认连接
        generateDefault();
    }

    public ZkDataSourceFactory() {
        setSingleton(false);
    }

    /**
     * 初始化默认连接
     */
    private static void generateDefault() {
        String url = ZkHelper.defaultConnection[0];
        String username = ZkHelper.defaultConnection[1];
        String password = ZkHelper.defaultConnection[2];
        config(url, username, password);
    }

    /**
     * 配置数据源，模拟项目忽略并发时的线程安全问题
     *
     * @return
     */
    public static void config(String addr, String username, String password) {
        // 如果更新信息与当前连接信息一致，则不做更新
        if (addr != null && username != null && password != null && addr.equals(ZkDataSourceFactory.addr) && username.equals(ZkDataSourceFactory.username) && password.equals(ZkDataSourceFactory.password)) {
            log.info("更新连接与当前一致，跳过更新");
            return;
        }

        // 新建数据源
        HikariDataSource dataSource = new HikariDataSource();
        if (addr != null) {
            ZkDataSourceFactory.addr = addr;
        }
        if (username != null) {
            ZkDataSourceFactory.username = username;
        }
        if (password != null) {
            ZkDataSourceFactory.password = password;
        }

        dataSource.setJdbcUrl(String.format("jdbc:mysql://%s?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&autoReconnect=true", ZkDataSourceFactory.addr));
        dataSource.setUsername(ZkDataSourceFactory.username);
        dataSource.setPassword(ZkDataSourceFactory.password);
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");

        // 获取旧数据源
        HikariDataSource oldDatasource = ZkDataSourceFactory.dataSource;
        // 设置新数据源
        ZkDataSourceFactory.dataSource = dataSource;
        // 触发JdbcTemplate工厂重建Bean
        JDBCTemplateFactory.refresh();
        // 如果旧数据源存在，则进行释放
        if (oldDatasource != null) {
            oldDatasource.close();
        }
        log.info("Datasource 切换至 {}", StringUtils.arrayToDelimitedString(new String[]{addr, username, password}, ","));
    }

    @Override
    public Class<?> getObjectType() {
        return DataSource.class;
    }

    @Override
    protected DataSource createInstance() {
        return dataSource;
    }

}
